package nc.bs.gl.voucher_list.event.util;


import nc.bs.common.util.DefDocQueryUtil;
import nc.bs.framework.common.NCLocator;

import nc.bs.gl.event.IGlConst;
import nc.bs.pub.util.BaseDaoUtil;
import nc.itf.gl.voucher.IVoucher;
import nc.jdbc.framework.processor.ArrayListProcessor;
import nc.jdbc.framework.processor.ArrayProcessor;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.vo.bc.pub.util.OrgAccessor;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.pm.util.CollectionUtils;
import nc.vo.pub.BusinessException;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static nc.bs.common.util.OrgQueryUtil.getPkOrgByCode;


/**
 * @author duanyp1
 * @date 2024/2/20 14:47
 */
public class SortDetailIndexUtil {

    public static void sortAfterInsert(VoucherVO[] bill) throws BusinessException {
        refreshVoucherDetailIndex(bill);
    }

    public static void sortAfterUpdate(VoucherVO[] bill) throws BusinessException {
        refreshVoucherDetailIndex(bill);
    }

    public static void sortAfterDelete(VoucherVO[] bill) throws BusinessException {
        refreshVoucherDetailIndex(bill);
    }

    public static String[] querySortOrg() {
        DefdocVO[] orgDocs = DefDocQueryUtil.queryDefDocByListCode(IGlConst.CSortIndexOrg);
        return ObjectUtils.isEmpty(orgDocs) ? new String[0] : Arrays.stream(orgDocs).map(DefdocVO::getShortname).toArray(String[]::new);
    }

    public static Set<String> querySortFilterOrgPeriod() {
        DefdocVO[] orgPeriods = DefDocQueryUtil.queryDefDocByListCode(IGlConst.CSortIndexOrgPeriod);
        if (ObjectUtils.isEmpty(orgPeriods)) return new HashSet<>();
        //组织编码 + 会计期间
        return Arrays.stream(orgPeriods).collect(HashSet::new, (set, doc) -> set.add(doc.getShortname() + doc.getMnecode()), (i, doc) -> {
        });
    }

    private static void refreshVoucherDetailIndex(VoucherVO[] bill) throws BusinessException {
        List<String> ids = (List<String>) BaseDaoUtil.getInstance().executeQuery(buildQueryConditionSQL(bill), new ColumnListProcessor());
        if (CollectionUtils.isEmpty(ids)) return;
        IVoucher service = NCLocator.getInstance().lookup(IVoucher.class);
        VoucherVO[] rsa = service.queryByPks(ids.toArray(new String[0]));
        if(ArrayUtils.isEmpty(rsa)) return;
        List<VoucherVO> rs = Arrays.asList(rsa);
        Set<String> ups = new HashSet<>();
        for (VoucherVO voucherVO : bill) {
            ups.add(voucherVO.getPk_prepared());
            ups.add(voucherVO.getCreator());
        }
        Set<String> periods = querySortFilterOrgPeriod();
        List<VoucherVO> collect = rs.stream().filter(i -> !periods.contains(OrgAccessor.getDocByPk(i.getPk_org()).getCode() + i.getYear() + i.getPeriod())).collect(Collectors.toList());
        for (String person : ups) {
            List<VoucherVO> temp = collect.stream()
                    .filter(i -> i.getPk_prepared().equals(person))
                    .sorted(Comparator.comparing(VoucherVO::getCreationtime))
                    .sorted(Comparator.comparingInt(i -> (i.getNo() == null ? Integer.MAX_VALUE : i.getNo())))
                    .collect(Collectors.toList());
            Integer index = 1;
            for (VoucherVO voucherVO : temp) {
                if (voucherVO.getFree2() == null || index.compareTo(Integer.valueOf(voucherVO.getFree2())) != 0) {
                    BaseDaoUtil.getInstance().executeUpdate("update gl_voucher set free2 = " + (index) + " where pk_voucher = '" + voucherVO.getPk_voucher() + "'");
                }
                index++;
            }
        }
    }


    private static String buildQueryConditionSQL(VoucherVO[] bill) {
        StringBuilder builder = new StringBuilder();
        builder.append("SELECT pk_voucher FROM gl_voucher WHERE ");
        //1、需要参与排序的组织
        String[] sortOrg = querySortOrg();
        String orgValues = Arrays.stream(sortOrg).distinct().map(pk_org -> "'" + getPkOrgByCode(pk_org) + "'")
                .collect(Collectors.joining(", ", "(", ")"));
        //2、需要参与排序的会计期间
        String yearPeriodValues = Arrays.stream(bill).map(voucher -> "'" + voucher.getYear() + voucher.getPeriod() + "'")
                .collect(Collectors.joining(", ", "(", ")"));
        //3、需要参与排序的制单人
        String pkPreparedValues = Arrays.stream(bill).map(VoucherVO::getPk_prepared).distinct()
                .map(pkPrepared -> "'" + pkPrepared + "'").collect(Collectors.joining(", ", "(", ")"));
        //4、需要参与排序的创建人
        String creatorValues = Arrays.stream(bill).map(VoucherVO::getCreator).distinct()
                .map(creator -> "'" + creator + "'").collect(Collectors.joining(", ", "(", ")"));
        builder.append("year || period IN ").append(yearPeriodValues);
        builder.append(" AND (");
        builder.append("pk_prepared IN ").append(pkPreparedValues);
        builder.append(" OR ");
        builder.append("creator IN ").append(creatorValues);
        builder.append(")");
        builder.append(" and pk_org in ").append(orgValues);
        return builder.toString();
    }

}
